/**
 * H5文件上传
 * Made by Wangcheng @2019
 * 
 * 使用方式：
 * 1.引入   
 * import { UploadLight } from "./UploadLight";
 * 
 * 2.new初始化  
 * let Up = new UploadLight(opts);
 * 
 * 3.调用click方法   
 * Up.handleUploadClick();
 */
export class UploadLight {
  constructor(options) {
    this.inputEl = null;//当前文件DOM对象
    this.rebuildFiles = [];//文件blob转base64
    this.MAX_SIZE = 1048576 * 5;//最大上传限制

    /**
     * 可配置参数
     */
    const defaultOptions = {
      name: "file",
      ref: "fileInputRef",
      accept: "image/*",// 文件类型 ...
      multiple: "",//多选 multiple
      capture: '',//打开方式 camera ...  
      maxSize: this.MAX_SIZE,//文件大小
      onChange: this.handleFileChangeDefault,
      onReadFiles: filesObj => { console.log('defaultOptions.onReadFiles:', filesObj) },//可返回文件数据（原始+转化后）
    }
    this.options = Object.assign({}, defaultOptions, options);
    console.log('this.options:', this.options)
    this.handleFileChangeDefault = this.handleFileChangeDefault.bind(this);
    this.handleReadFilesDefault = this.handleReadFilesDefault.bind(this);
  }

  /**
  * 触发打开文件操作
  * 创建input标签并触发click
  * @param {Object} options
  */
  handleUploadClick() {
    this.inputEl = document.createElement("input");
    this.inputEl.setAttribute("type", "file");
    this.inputEl.setAttribute("ref", this.options.ref);
    this.inputEl.setAttribute("accept", this.options.accept);
    this.inputEl.setAttribute("name", this.options.name);
    if (this.options.multiple) {
      this.inputEl.setAttribute("multiple", "multiple");//是否支持多文件选择
    }
    if (this.options.capture) {
      this.inputEl.setAttribute("capture", "camera");//是否支持摄像头拍照照片文件
    }
    this.inputEl.onchange = this.options.onChange.bind(this);
    this.inputEl.style.display = "none";
    document.body.appendChild(this.inputEl);
    this.inputEl.click();
    // console.log("this.inputEl:", this.inputEl);
  }

  /**
   * 将Blob or File文件通过readAsDataURL转化成img可识别的格式
   * @param {*} files
   */
  handleFileChangeDefault(e) {
    let files = e.target.files || e.dataTransfer.files;
    console.log("user selected files:", files);
    if (!files.length) return;
    return this.handleReadFilesDefault(files);
  }

  handleReadFilesDefault(files) {
    this.rebuildFiles = []
    if (typeof FileReader === "undefined") {
      alert("您的浏览器不支持图片上传，请升级/切换您的浏览器");
      return false;
    }
    files = Array.prototype.slice.call(files);//非数组对象转数组
    let openFiles = files.length;

    /**过滤不符合规则的文件 */
    for (let i = 0; i < files.length; i++) {
      if (files[i].size > this.MAX_SIZE) {
        alert(`请控制文件大小在${this.MAX_SIZE / 1024 / 1024}MB以内`);
        if (openFiles == 1) {
          this.inputEl.value = "";
          console.log('清空文件内容')
        }
        files.splice(i, 1);
        console.log('files:', files)
      }
    }

    /**（可用文件）文件读取 readAsDataURL 并返回处理后的文件数据 */
    for (let i = 0; i < files.length; i++) {
      let currFile = files[i];
      const { name, type } = currFile;
      let reader = new FileReader();
      reader.readAsDataURL(currFile);

      /**文件读取中 */
      reader.onload = e => {
        this.rebuildFiles.push({
          file: e.target.result,
          name: name || '',
          type: type,
        });

        /**异步回调触发条件 */
        if (this.rebuildFiles.length == files.length) {
          let filesObj = {
            originFiles: files,
            rebuildFiles: this.rebuildFiles
          };
          return new Promise((resolve, reject) => {
            try {
              this.options.onReadFiles(filesObj);
              resolve(filesObj);
            } catch (err) {
              reject({ error: 1, msg: 'read file error', data: err });
            }
          })
        }
      };

      /**当前文件读取完成 */
      reader.onloadend = e => {
        // console.log('文件读取完成 e:', e)
      }

      /**当前文件读取发生错误 */
      reader.onerror = e => {
        console.log('文件读取错误 e:', e)
        reader.abort();
      }
    }
  }
}
